/** @file */ 

#pragma once

#include <string>
#include "Utilities.h"


namespace ZeEngine
{
    class XMLParsers;

    class GameConfiguration 
    {

     public:

        GameConfiguration();
        ~GameConfiguration();

        bool LoadConfig(const std::string& iConfigFile);

        /**
         * @brief Returns the number of ticks per second
         *
         * @return The number of updates per second
         */
        inline u32 GetTicksPerSecond()      const { return m_TicksPerSecond; }

        /**
         * @brief Returns the duration of each tick
         *
         * @return The duration of each tick in MS
         */
        inline u32 GetSkipTicks()           const { return m_SkipTicks;      }

        /**
         * @brief Returns the maximum number of frames to be skipped
         * 
         * This really only applies if the rendering is starting to slow down and we have to ensure a constant game speed
         *
         * @return The maximum number of frames that we can skip before forcing a render.
         */
        inline u32 GetMaxFrameskip()        const { return m_MaxFrameSkip;   }

        /**
         * @brief Returns the screen width in pixels
         * 
         * @return The screen width in pixels
         */
        inline u32 GetScreenWidth()         const { return m_ScreenWidth;    }

        /**
         * @brief Returns the screen height in pixels
         * 
         * @return The screen height in pixels
         */
        inline u32 GetScreenHeight()        const { return m_ScreenHeight;   }

        /**
         * @brief Returns the screen bits per pixel
         * 
         * @return The screen bits per pixel
         */
        inline u32 GetScreenBPP()           const { return m_ScreenBPP;      }

        /**
         * @brief Returns the caption of the screen
         *
         * @return The caption of the window
         */
        inline const std::string& GetCaption() const { return m_Caption; }

        /**
         * @brief Returns the icon of the screen
         *
         * @return The icon of the window
         */
        inline const std::string& GetIcon() const { return m_Icon; }

        inline const bool GetFullScreen() const { return m_FullScreen; }

        inline const bool GetShowMouse() const { return m_ShowMouse; }

        inline Vector2D<u32> GetScreenResolution() const { return Vector2D<u32>(GetScreenWidth(), GetScreenHeight()); }

        inline Vector2D<u32> GetLogicalResolution() const { return m_ScreenLogicalResolution; }

    private:

        /**
         * @brief Sets the number of ticks per second
         *
         * @oaram iTicksPerSecond The number of updates per second
         */
        inline void SetTicksPerSecond(u32 iTicksPerSecond) { m_TicksPerSecond = iTicksPerSecond; m_SkipTicks = 1000 / m_TicksPerSecond; }

        /**
         * @brief Sets the maximum number of frames to be skipped
         * 
         * This really only applies if the rendering is starting to slow down and we have to ensure a constant game speed
         *
         * @param iMaxFrameSkip The maximum number of frames that we can skip before forcing a render.
         */
        inline void SetMaxFrameskip(u32 iMaxFrameSkip) { m_MaxFrameSkip = iMaxFrameSkip; }

        /**
         * @brief Sets the screen width in pixels
         * 
         * @param iWidth The screen width in pixels
         */
        inline void SetScreenWidth(u32 iWidth) { m_ScreenWidth = iWidth; }

        /**
         * @brief Sets the screen height in pixels
         * 
         * @param iHeight The screen height in pixels
         */
        inline void SetScreenHeight(u32 iHeight) { m_ScreenHeight = iHeight; }

        /**
         * @brief Sets the screen bits per pixel
         * 
         * @param iScreenBPP The screen bits per pixel
         */
        inline void SetScreenBPP(u32 iScreenBPP) { m_ScreenBPP = iScreenBPP; }

        /**
         * @brief Sets the caption of the screen
         *
         * @param iCaption The caption of the window
         */
        inline void SetCaption(const std::string& iCaption) { m_Caption = iCaption; }

        inline void SetLogicalResolution(const Vector2D<u32>& iLogicalResolution) { m_ScreenLogicalResolution = iLogicalResolution; }

        /**
         * @brief Sets the icon of the screen
         *
         * @param iIcon The icon to use
         */
        inline const void SetIcon(const std::string& iIcon) { m_Icon = iIcon; }

        template <typename T>
        void SetSettingFromXml(const std::string& iPath, T& oValue)
        {
            if (m_pXMLConfig->ValueExists(iPath))
            {
                oValue = m_pXMLConfig->GetValue<T>(iPath);
            }
        }

        bool SetBooleanFromXml(const std::string& iPath);

        static const u32      cDefaultTicksPerSecond = 25;
        static const u32      cDefaultSkipTicks       = 1000 / cDefaultTicksPerSecond;
        static const u32      cDefaultMaxFrameSkip    = 5;

        static const u32      cDefaultScreenWidth     = 1024;
        static const u32      cDefaultScreenHeight    = 768;
        static const u32      cDefaultScreenBPP       = 32;

        static const std::string cDefaultCaption;
        static const std::string cDefaultIcon;

        static const bool    cFullScren;
        static const bool    cShowMouse;

        static const u32     cDefaultLogicalResolutionX = 1600;
        static const u32     cDefaultLogicalResolutionY = 900;

        u32         m_TicksPerSecond;
        u32         m_SkipTicks;
        u32         m_MaxFrameSkip;

        u32         m_ScreenHeight;
        u32         m_ScreenWidth;
        u32         m_ScreenBPP;

        std::string    m_Caption;
        std::string    m_Icon;

        bool        m_FullScreen;
        bool        m_ShowMouse;

        Vector2D<u32> m_ScreenLogicalResolution;

        XMLParsers*     m_pXMLConfig;
    
    };
}
